package cn.funeralobjects.rms.service.impl;

import cn.funeralobjects.common.jpa.service.CommonCloudCrudJpaService;
import cn.funeralobjects.common.repository.CommonCloudRepository;
import cn.funeralobjects.common.service.annotataion.CommonRollback;
import cn.funeralobjects.common.service.annotataion.CommonService;
import cn.funeralobjects.common.service.exception.DataConflictException;
import cn.funeralobjects.rms.BasicInfo;
import cn.funeralobjects.rms.entity.*;
import cn.funeralobjects.rms.enums.ResStatus;
import cn.funeralobjects.rms.model.Res;
import cn.funeralobjects.rms.model.ResUploadRecord;
import cn.funeralobjects.rms.repository.EResRepository;
import cn.funeralobjects.rms.repository.EResUploadRecordRepository;
import cn.funeralobjects.rms.service.ResService;
import cn.funeralobjects.util.Assert;
import cn.funeralobjects.util.NumberUtils;
import cn.funeralobjects.util.annotation.ArgHasLength;
import cn.funeralobjects.util.annotation.ArgNonNull;
import cn.funeralobjects.util.annotation.ArgNotZero;
import cn.funeralobjects.util.annotation.AssertArg;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.JPQLQueryFactory;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * @author FuneralObjects
 * Create date: 2020/6/7 1:41 AM
 */
@CommonService
public class ResServiceImpl implements ResService, CommonCloudCrudJpaService<Res, ERes, Integer> {

    @Resource
    private EResRepository eResRepository;

    @Resource
    private EResUploadRecordRepository uploadRecordRepository;

    @Resource
    private JPQLQueryFactory jpqlQueryFactory;

    @Override
    public CommonCloudRepository<ERes, Integer> commonCloudRepository() {
        return eResRepository;
    }

    @AssertArg
    @Override
    public void checkConflict(@AssertArg Res res) throws DataConflictException {
        this.mustNotConflictByCode(res.getCode());
    }

    @Override
    public ERes toEntity(Res res) {
        if (res == null) {
            return null;
        }
        ERes entity = new ERes();
        EResGroup eResGroup = new EResGroup();
        eResGroup.setId(res.getResGroupId());
        entity.setStatus(res.getStatus())
                .setBucketCode(res.getBucketCode())
                .setResGroup(eResGroup)
                .setCode(res.getCode())
                .setName(res.getName());
        return entity;
    }

    @AssertArg
    @Override
    public void checkConflict(@AssertArg Res res, Integer withoutId) throws DataConflictException {
        this.mustNotConflictByCode(res.getCode(), withoutId);
    }

    @Override
    public void copyToEntity(Res sourceModify, ERes targetEntity) {
        targetEntity.setBucketCode(sourceModify.getBucketCode())
                .setStatus(sourceModify.getStatus())
                .setCode(sourceModify.getCode())
                .setName(sourceModify.getName());

    }

    @Override
    public boolean isValid(Integer id) {
        return NumberUtils.notZero(id);
    }

    @Override
    public void validateModify(Res res) {
        Assert.argAssert(res, "res");
    }

    @Override
    public String getName() {
        return ENTITY_NAME;
    }

    @Override
    public String getModuleName() {
        return BasicInfo.MODULE;
    }

    @CommonRollback
    @AssertArg
    @Override
    public ERes add(Res res, @ArgHasLength String path) {
        ERes entity = this.add(res);
        uploadRecordRepository.save(new EResUploadRecord().setPath(path).setResId(entity.getId()));
        return entity;
    }

    @Override
    public Optional<ResUploadRecord> getUploadRecord(Integer id) {
        Tuple tuple = jpqlQueryFactory.select(QERes.eRes.id,
                QERes.eRes.code,
                QERes.eRes.name,
                QERes.eRes.status,
                QERes.eRes.bucketCode,
                QEResUploadRecord.eResUploadRecord.path
        ).from(QERes.eRes)
                .join(QEResUploadRecord.eResUploadRecord).on(QEResUploadRecord.eResUploadRecord.resId.eq(QERes.eRes.id))
                .where(QERes.eRes.id.eq(id).and(QERes.eRes.delSalt.eq(getExistsDelSalt())))
                .fetchOne();
        return Optional.ofNullable(tuple)
                .map(t -> new ResUploadRecord()
                        .setBucketCode(tuple.get(QERes.eRes.bucketCode))
                        .setCode(tuple.get(QERes.eRes.code))
                        .setName(tuple.get(QERes.eRes.name))
                        .setPath(tuple.get(QEResUploadRecord.eResUploadRecord.path))
                        .setStatus(tuple.get(QERes.eRes.status)));
    }

    @CommonRollback
    @AssertArg
    @Override
    public void updateStatus(@ArgNotZero Integer id, @ArgNonNull ResStatus status) {
        eResRepository.updateStatusByIdAndDelSalt(status, id, getExistsDelSalt());
    }

    private Integer getExistsDelSalt() {
        return (Integer) eResRepository.getDefaultExistsDelSalt();
    }
}
